package com.shanxia.codec.cmd;

import com.shanxia.codec.ProtocolDataBase;
import com.shanxia.codec.enums.DecodeEnum;
import lombok.Data;

import java.math.BigDecimal;
import java.util.Arrays;

import static com.shanxia.codec.CodeConstant.HUNDRED;
import static com.shanxia.codec.CodeConstant.PERCENT;
import static com.shanxia.codec.Decoder.*;

/**
 * S -> C
 * 平台回复”即插即充“请求充电结果
 */
@Data
public class Cmd207 extends ProtocolDataBase {

    public static final int MIN_SIZE = 130;

    private int v1;
    private int v2;
    private String sn;                      // 充电桩编码
    private int pileNum;                    // 充电枪号
    private String vin;                     // 车辆VIN码
    private String bindAccount;             // 车辆VIN绑定账号
    private String serial;                  // 充电流水号
    private int code;                       // 验证结果
    private int reason;                     // 验证原因
    private double balance;                 // 可充电余额
    private String pwd;                     // 屏幕停机密码

    public Cmd207(){
        super.setCmd(207);
    }

    public static Cmd207 decodeFromBase(ProtocolDataBase protocolDataBase) {
        Cmd207 cmd = new Cmd207();
        cmd.copyDataFrom(protocolDataBase);
        byte[] dataField = protocolDataBase.getDataField();
        //数据域长度
        if (dataField.length < MIN_SIZE) {
            cmd.setResult(DecodeEnum.InvalidData);
            return cmd;
        }
        int offset = 0;
        cmd.v1 = getUint16(dataField, offset);
        offset += 2;
        cmd.v2 = getUint16(dataField, offset);
        offset += 2;
        // 32字节充电桩编码
        cmd.sn = byteToAscii(Arrays.copyOfRange(dataField, offset, offset + 32), true);
        offset += 32;
        // 1字节充电枪号
        cmd.pileNum = getUint8(dataField[offset++]);
        // 17字节车辆 VIN 码
        cmd.vin = byteToAscii(Arrays.copyOfRange(dataField, offset, offset + 17), true);
        offset += 17;
        // 32字节车辆 VIN 绑定账号
        cmd.bindAccount = byteToAscii(Arrays.copyOfRange(dataField, offset, offset + 32), true);
        offset += 32;
        // 32字节充电流水号
        cmd.serial = byteToAscii(Arrays.copyOfRange(dataField, offset, offset + 32), true);
        offset += 32;
        // 1字节验证结果
        cmd.code = getUint8(dataField[offset++]);
        // 1字节验证原因
        cmd.reason = getUint8(dataField[offset++]);
        // 4字节可充电余额
        cmd.balance = new BigDecimal(bytesToIntLittle(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 4;
        // 6字节屏幕停机密码
        cmd.pwd = byteToAscii(Arrays.copyOfRange(dataField, offset, offset + 6), true);
        return cmd;
    }

    @Override
    public byte[] getDataField() {
        byte[] data = new byte[MIN_SIZE];
        int offset = 0;
        getBytesAsUint16(data, offset, this.v1);
        offset += 2;
        getBytesAsUint16(data, offset, this.v2);
        offset += 2;
        // 32字节充电桩编码
        encodeAscii(data, this.sn, 32, offset);
        offset += 32;
        // 1字节充电枪号
        data[offset++] = (byte) pileNum;
        // 17字节车辆 VIN 码
        encodeAscii(data, this.vin, 17, offset);
        offset += 17;
        // 32字节车辆VIN绑定账号
        // 如无则填0xff. 离线充电则由桩填写空
        if (bindAccount == null || "".equals(bindAccount)) {
            for (int i = 0; i < 32; i ++) {
                data[offset + i] = (byte) 0xFF;
            }
        } else {
            encodeAscii(data, this.bindAccount, 32, offset);
        }
        offset += 32;
        // 32字节充电流水号
        encodeAscii(data, this.serial, 32, offset);
        offset += 32;
        // 1字节验证结果
        data[offset++] = (byte) code;
        // 1字节验证原因
        data[offset++] = (byte) reason;
        // 4字节可充电余额
        intToBytesLittle(data, offset, new BigDecimal(String.valueOf(this.balance)).multiply(HUNDRED).intValue());
        // 6字节屏幕停机密码
        // 如无则填0xff. 离线充电则由桩填写空
        if (pwd == null || "".equals(pwd)) {
            for (int i = 0; i < 6; i ++) {
                data[offset + i] = (byte) 0xFF;
            }
        } else {
            encodeAscii(data, this.pwd, 6, offset);
        }
        return data;
    }
}
